package in.xiandan.mmrc.example;

import android.Manifest;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.PermissionChecker;
import androidx.exifinterface.media.ExifInterface;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.blankj.utilcode.util.ToastUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.tbruyelle.rxpermissions2.Permission;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.zhihu.matisse.Matisse;
import com.zhihu.matisse.MimeType;
import com.zhihu.matisse.event.MessageWrap;
import com.zhihu.matisse.internal.entity.CaptureStrategy;
import com.zhihu.matisse.listener.OnCheckedListener;
import com.zhihu.matisse.listener.OnSelectedListener;

import org.greenrobot.eventbus.EventBus;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import in.xiandan.mmrc.MediaMetadataConfig;
import in.xiandan.mmrc.MediaMetadataKey;
import in.xiandan.mmrc.MediaMetadataResource;
import in.xiandan.mmrc.MediaMetadataRetrieverCompat;
import in.xiandan.mmrc.MediaMetadataRetrieverFactory;
import in.xiandan.mmrc.example.custom.CustomFormatChecker;
import in.xiandan.mmrc.example.custom.CustomKey;
import in.xiandan.mmrc.example.custom.SVGMediaMetadataRetrieverFactory;
import in.xiandan.mmrc.fileformat.UnknownFileFormatException;
import in.xiandan.mmrc.retriever.AndroidMediaMetadataRetrieverFactory;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity {
    TextView tv;
    TextView tv_bite_rate;
    EditText ed;
    RecyclerView rv;
    Spinner spinner;
    Spinner spinner_frame;
    Spinner spinner_size;

    private ThumbnailAdapter mThumbnailAdapter;

    private Disposable mThumbnailDisposable;

    private List<String> mKeys;

    private int mSizeType = CENTER_CROP;
    private int mFetchFrameOption = MediaMetadataKey.OPTION_CLOSEST_SYNC;
    private Class<MediaMetadataRetrieverFactory> mRetrieverFactoryCls;

    private static final int CENTER_CROP = 0;
    private static final int ORIGINAL_SIZE = 1;
    private static final int FLOOR_SCALE = 2;
    RxPermissions rxPermissions = new RxPermissions(this);
    private int RC_CHOOSE_PHOTO = 1;
    private int RC_PHOTO_PREVIEW = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        ed = (EditText) findViewById(R.id.ed);
        rv = (RecyclerView) findViewById(R.id.rv);
        spinner = (Spinner) findViewById(R.id.spinner);
        spinner_frame = (Spinner) findViewById(R.id.spinner_frame);
        spinner_size = (Spinner) findViewById(R.id.spinner_size);
        tv_bite_rate = (TextView) findViewById(R.id.tv_bite_rate);

        //ed.setText("http://p19.qhimg.com/bdr/__85/t01a05462d1b63252e4.jpg");
        //ed.setText("http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f20.mp4");
        ed.setText("/storage/emulated/0/DCIM/Camera/VID_20200516_184955.mp4");

        //应用全局配置
        MediaMetadataConfig.newBuilder()
                .addFileFormatChecker(new CustomFormatChecker())
                .addCustomRetrieverFactory(new SVGMediaMetadataRetrieverFactory())
                .build()
                .apply();

        mKeys = getAllKeys();

        rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));


        final List<MediaMetadataRetrieverFactory> factories = MediaMetadataResource.globalConfig().getFactories();
        spinner.setAdapter(new ArrayAdapter<String>(this, R.layout.simple_spinner_dropdown_item, new String[factories.size() + 1]) {
            @Override
            public String getItem(int position) {
                return position == 0 ? "自动" : factories.get(position - 1).getClass().getSimpleName().replace("Factory", "");
            }
        });
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (position == 0) {
                    mRetrieverFactoryCls = null;
                } else {
                    try {
                        mRetrieverFactoryCls = (Class<MediaMetadataRetrieverFactory>) factories.get(position - 1).getClass();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
        final String[] fetchFrame = new String[]{"OPTION_CLOSEST_SYNC", "OPTION_CLOSEST", "OPTION_PREVIOUS_SYNC", "OPTION_NEXT_SYNC"};
        spinner_frame.setAdapter(new ArrayAdapter<String>(this, R.layout.simple_spinner_dropdown_item, fetchFrame));
        spinner_frame.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                try {
                    final Field field = MediaMetadataKey.class.getField(fetchFrame[position]);
                    mFetchFrameOption = field.getInt(null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        final String[] sizes = new String[]{"CenterCrop", "原始尺寸", "向下缩放"};
        spinner_size.setAdapter(new ArrayAdapter<String>(this, R.layout.simple_spinner_dropdown_item, sizes));
        spinner_size.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                mSizeType = position;
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        checkPermission();

        bindExampleRecyclerView((RecyclerView) findViewById(R.id.rv_image), "sample-image", 5);
        bindExampleRecyclerView((RecyclerView) findViewById(R.id.rv_audio), "sample-audio", 5);
        bindExampleRecyclerView((RecyclerView) findViewById(R.id.rv_video), "sample-video", 4);
        bindExampleRecyclerView((RecyclerView) findViewById(R.id.rv_custom), "sample-custom", 4);

    }

    private List<String> getAllKeys() {
        List<String> keys = new ArrayList<>();
        final Field[] fields = MediaMetadataKey.class.getFields();
        for (Field field : fields) {
            if (!field.getName().startsWith("OPTION")) {
                try {
                    keys.add((String) field.get(null));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        final Field[] exifFields = ExifInterface.class.getFields();
        for (Field field : exifFields) {
            if (field.getName().startsWith("TAG")) {
                try {
                    keys.add((String) field.get(null));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        //自定义
        final Field[] customFields = CustomKey.class.getFields();
        for (Field field : customFields) {
            if (field.getName().startsWith("METADATA_KEY")) {
                try {
                    keys.add((String) field.get(null));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return keys;
    }

    private void bindExampleRecyclerView(RecyclerView recyclerView, String dir, int spanCount) {
        recyclerView.setLayoutManager(new GridLayoutManager(this, spanCount));
        final ExampleAdapter adapter = new ExampleAdapter(this, dir);
        adapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
            @Override
            public void oOnItemClick(File exampleFile) {
                onItemClickMediaMetadata(exampleFile.getAbsolutePath());
            }
        });
        recyclerView.setAdapter(adapter);

    }

    private MediaMetadataRetrieverCompat mMmrc;

    public void clickMediaMetadata(View v) {
        final String input = ed.getText().toString();
        if (!TextUtils.isEmpty(input)) {
            onItemClickMediaMetadata(input);
        }
        try {
            mMmrc = new MediaMetadataRetrieverCompat();
            //给MediaMetadataRetriever设置数据源或抛出异常 并指定检索器
            try {
                mMmrc.setDataSourceOrThrow(URLSource.create(this, input), AndroidMediaMetadataRetrieverFactory.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
            long bitrate = mMmrc.extractMetadataLong(MediaMetadataKey.BITRATE, 0);
            tv_bite_rate.setText("比特率（码率）：" + bitrate / 1024 / 1024 + "m" + ">" + bitrate);
            System.out.println(bitrate);
        } catch (Exception e) {
            System.out.println("不是视频文件");
        }

    }

    public void clickMediaMetadata2(View v) {
        rxPermissions.requestEachCombined(Manifest.permission.CAMERA,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(new Consumer<Permission>() {
                    @Override
                    public void accept(Permission permission) throws Exception {
                        if (permission.granted) {
                            Matisse.from(MainActivity.this)
                                    .choose(MimeType.ofAll(), true)
                                    .countable(true)
                                    .capture(true)
                                    .captureStrategy(
                                            new CaptureStrategy(true, "com.meifa.app.fileprovider"))
                                    .maxSelectable(9)
//                                    .addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))
                                    .gridExpectedSize(
                                            getResources().getDimensionPixelSize(R.dimen.grid_expected_size))
                                    .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                                    .thumbnailScale(0.85f)
//                                            .imageEngine(new GlideEngine())  // for glide-V3
                                    .imageEngine(new Glide4Engine())    // for glide-V4
                                    .setOnSelectedListener(new OnSelectedListener() {
                                        @Override
                                        public void onSelected(
                                                @androidx.annotation.NonNull List<Uri> uriList, @androidx.annotation.NonNull List<String> pathList) {
                                            // DO SOMETHING IMMEDIATELY HERE
                                            Log.e("onSelected", "onSelected: pathList=" + pathList);
                                            //TODO 在这里判断如果是选择了视频文件，那么直接按确定键（通过模拟点击来实现）,后发现模拟点击拿不到确定按钮的空间，所以还是直接finish界面，返回uri，然后上一个界面改变布局，隐藏掉九宫格选择器，用一个video控件预览选中的视频
                                            Set<MimeType> mimeTypes = MimeType.ofVideo();
                                            for (MimeType type : mimeTypes) {
                                                if (uriList.size() > 0 && type.checkType(getContentResolver(), uriList.get(0))) {
                                                    System.out.println("选中了视频:" + type.name());
                                                    EventBus.getDefault().post(MessageWrap.getInstance("evenbus_select_video"));
                                                    System.out.println("IssueActivity" + "发送订阅事件");
                                                }
                                            }
                                        }
                                    })
                                    .originalEnable(true)
                                    .maxOriginalSize(10)
                                    .setOnCheckedListener(new OnCheckedListener() {
                                        @Override
                                        public void onCheck(boolean isChecked) {
                                            // DO SOMETHING IMMEDIATELY HERE
                                            Log.e("isChecked", "onCheck: isChecked=" + isChecked);
                                        }
                                    })
                                    .forResult(RC_CHOOSE_PHOTO);
                        } else if (permission.shouldShowRequestPermissionRationale) {
                            ToastUtils.showShort("您已拒绝权限申请");
                        } else {
                            //TODO 当用户手动进入设置界面把权限关掉的时候就会走这里
                            //TODO 可以直接跳转至设置界面
                            ToastUtils.showShort("您已手动在设置界面关闭了权限，请前往设置>应用管理>权限管理打开权限");
                        }
                    }
                });
    }

    private void onItemClickMediaMetadata(String input) {
        if (mThumbnailDisposable != null && !mThumbnailDisposable.isDisposed()) {
            mThumbnailDisposable.dispose();
        }

        final MediaMetadataRetrieverCompat mmrc = new MediaMetadataRetrieverCompat();

        Observable.just(input).flatMap((Function<String, ObservableSource<String>>) url -> {
            //设置数据源
            mmrc.setDataSourceOrThrow(URLSource.create(MainActivity.this, url), mRetrieverFactoryCls);
            //异步获取所有能拿到的值
            return obtainMetadataInfo(mmrc);
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .map(info -> {
                    tv.setText(info);
                    return info;
                })
                .map(s -> {
                    final long duration = mmrc.extractMetadataLong(MediaMetadataKey.DURATION, 0);
                    //每1秒取一帧
                    final long interval = 1000;
                    //最少取一帧 最多取10帧
                    final int itemCount = (int) Math.min(Math.max(1, duration / interval), 10);
                    mThumbnailAdapter = new ThumbnailAdapter(itemCount);
                    rv.setAdapter(mThumbnailAdapter);
                    return itemCount;
                })
                .observeOn(Schedulers.io())
                .flatMap((Function<Integer, ObservableSource<ThumbnailBitmap>>) itemCount -> {
                    //异步获取帧缩略图
                    return obtainThumbnail(mmrc, itemCount);
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<ThumbnailBitmap>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        mThumbnailDisposable = d;
                        tv.setText(null);
                    }

                    @Override
                    public void onNext(ThumbnailBitmap thumbnail) {
                        //缩略图更新到RecyclerView
                        mThumbnailAdapter.setThumbnail(thumbnail);
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        if (e instanceof UnknownFileFormatException) {
                            Toast.makeText(MainActivity.this, "不支持此格式", Toast.LENGTH_SHORT).show();
                        } else if (e instanceof FileNotFoundException) {
                            Toast.makeText(MainActivity.this, "此文件不存在", Toast.LENGTH_SHORT).show();
                        } else if (e instanceof IOException) {
                            Toast.makeText(MainActivity.this, "检索器创建失败", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(MainActivity.this, "获取失败" + e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onComplete() {
                        mmrc.release();
                    }
                });
    }

    private Observable<ThumbnailBitmap> obtainThumbnail(MediaMetadataRetrieverCompat mmrc, int itemCount) {
        //每500毫秒取一帧
        final long interval = 500;
        final int size = getResources().getDimensionPixelSize(R.dimen.thumbnail_size);
        //取帧是耗时的操作,需要放在子线程
        return Observable.create(new ObservableOnSubscribe<ThumbnailBitmap>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<ThumbnailBitmap> s) throws Exception {
                //异步获取缩略图
                for (int i = 0; i < itemCount; i++) {
                    long millis = i * interval;
                    Bitmap atTime;
                    if (ORIGINAL_SIZE == mSizeType) {
                        atTime = mmrc.getFrameAtTime(millis, mFetchFrameOption);
                    } else if (FLOOR_SCALE == mSizeType) {
                        atTime = mmrc.getScaledFrameAtTime(millis, mFetchFrameOption, size, size);
                    } else {
                        atTime = mmrc.getCenterCropFrameAtTime(millis, mFetchFrameOption, size, size);
                    }
                    s.onNext(new ThumbnailBitmap(i, atTime));
                }
                s.onComplete();
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 获取所有能拿到的值
     */
    private Observable<String> obtainMetadataInfo(final MediaMetadataRetrieverCompat mmrc) {
        return Observable.just("").map(new Function<String, String>() {
            @Override
            public String apply(String empty) throws Exception {
                StringBuilder sb = new StringBuilder();
                sb.append("Retriever：");
                sb.append(mmrc.getRetriever().getClass().getSimpleName());
                sb.append("\n");
                for (String key : mKeys) {
                    String value = mmrc.extractMetadata(key);
                    if (value != null) {
                        if (key.trim().equals("file_size")) {
                            sb.append("\n");
                            sb.append(key);
                            sb.append("：");
                            sb.append((Double.parseDouble(value) / 1024) / 1024);
                            sb.append("m");
                        }
                        sb.append("\n");
                        sb.append(key);
                        sb.append("：");
                        sb.append(value);
                    }
                }
                return sb.toString();
            }
        });

    }


    private void checkPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PermissionChecker.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PermissionChecker.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK) {
            return;
        }
        if (requestCode == RC_CHOOSE_PHOTO) {
            //处理Matisse选择到的图片
            System.out.println(Matisse.obtainResult(data).toString());
            System.out.println(Matisse.obtainPathResult(data).toString());
            Log.e("OnActivityResult ", String.valueOf(Matisse.obtainOriginalState(data)));
            ArrayList<String> pathResultList = (ArrayList<String>) Matisse.obtainPathResult(data);
            ArrayList<Uri> uriResultList = (ArrayList<Uri>) Matisse.obtainResult(data);
            ed.setText(pathResultList.get(0));
        }
    }
}
